
package com.sausageking.auth;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.sausageking.shared.Consumer;

public class PersistentLoginFilter implements Filter {

  private LoginTokenDao tokenService = new LoginTokenDao();

  @Override
  public void init(FilterConfig config) {
    // nothing for now
  }

  /**
   * If the session has a user attribute, consider this session is already
   * authenticated. Otherwise, look at the loginToken in the cookie, if it is a
   * valid token, also consider it authenticated, remove the old token and renew
   * the cookie with a new token.
   */
  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {

    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    Cookie tokenCookie = getCookieByName(httpRequest.getCookies(), "loginToken");

    HttpSession session = httpRequest.getSession();
    Consumer consumer = (Consumer) session.getAttribute("consumer");

    if (consumer == null && tokenCookie != null) {
      consumer = tokenService.loginWithToken(tokenCookie.getValue());
      String tokenValue = "";
      if (consumer != null) {
        tokenValue = tokenService.setupNewLoginToken(consumer).toString();
      }

      // Set user attribute in session.
      httpRequest.getSession().setAttribute("consumer", consumer);

      // Place a new login token in the cookie that is valid for another week.
      tokenCookie.setMaxAge(0);
      httpResponse.addCookie(tokenCookie);
      tokenCookie = new Cookie("loginToken", tokenValue);
      tokenCookie.setPath("/offersticker");
      tokenCookie.setMaxAge(24 * 7 * 60 * 60);
      httpResponse.addCookie(tokenCookie);
    }

    chain.doFilter(httpRequest, httpResponse);
  }

  @Override
  public void destroy() {
    // nothing for now
  }

  private Cookie getCookieByName(Cookie[] cookies, String name) {
    if (cookies == null || cookies.length == 0) {
      return null;
    }

    Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
    for (int i = 0; i < cookies.length; i++) {
      Cookie cookie = cookies[i];
      cookieMap.put(cookie.getName(), cookie);
    }
    return cookieMap.get(name);
  }

  public void setTokenService(LoginTokenDao tokenService) {
    this.tokenService = tokenService;
  }
}